package com.example;

import java.util.ArrayList;
import java.util.Random;
import java.util.Scanner;

public class ATM {
    // 创建一个存储账户对象的集合,后面每开一个账户,就往集合中添加一个账户对象
    private ArrayList<Account> accounts = new ArrayList<>();

    // 为了后面键盘录入方便一点,先创建好一个Scanner对象
    private Scanner sc = new Scanner(System.in);

    // 用于存放当前登录的用户对象
    private Account loginAcc;

    /**
     * 启动ATM系统 展示欢迎界面
     */
    public void start() {
        while (true) {
            System.out.println("=====欢迎您进入到了ATM系统=====");
            System.out.println("1.用户登录");
            System.out.println("2.用户开户");
            System.out.print("请输入你的选择：");
            int command = sc.nextInt();
            switch (command) {
                case 1:
                    // 用户登录
                    login();
                    break;
                case 2:
                    // 用户开户
                    createAccount();
                    break;
                default:
                    System.out.println("没有该操作~~");
            }
        }
    }

    /**
     * 用户登录功能
     */
    private void login() {
        System.out.println("=====系统登录=====");
        // 1.判断系统中是否存在账户对象,存在才能登录,如果不存在,我们直接结束登录操作
        if (accounts.size() == 0) {
            System.out.println("对不起,系统没有账户对象,请先开户~~");
            return; // 结束登录操作
        }

        // 2.系统中存在账户对象,可以进行登录操作
        while (true) {
            System.out.print("请您输入您的卡号：");
            String cardId = sc.next();
            // 3.判断这个卡号是否存在
            Account acc = getAccountById(cardId);
            if (acc == null) {
                // 说明这个卡号不存在
                System.out.println("您输入的卡号不存在,请您确认~~");
            } else {
                while (true) {
                    // 说明卡号存在,请用户输入密码
                    System.out.print("请您输入您的密码：");
                    String passWord = sc.next();
                    // 4.判断密码是否正确
                    if (acc.getPassWord().equals(passWord)) {
                        loginAcc = acc;
                        // 说明密码正确,登录成功
                        System.out.println("恭喜您," + acc.getUserName() + "成功登录了系统,您的卡号是：" + acc.getCardId());
                        // 展示登录后的界面
                        showMenu();
                        return; // 跳出并结束当前登录方法
                    } else {
                        System.out.println("您输入的密码错误,请您确认~~");
                    }
                }
            }
        }
    }

    /**
     * 展示登录后的界面
     */
    private void showMenu() {
        while (true) {
            System.out.println(loginAcc.getUserName() + "您可以选择如下功能进行账户的处理======");
            System.out.println("1.查询账户");
            System.out.println("2.存款");
            System.out.println("3.取款");
            System.out.println("4.转账");
            System.out.println("5.密码修改");
            System.out.println("6.退出");
            System.out.println("7.注销当前账户");
            System.out.print("请选择：");
            int command = sc.nextInt();
            switch (command) {
                case 1:
                    // 查询当前账户
                    showLoginAccount();
                    break;
                case 2:
                    // 存款
                    deposit();
                    break;
                case 3:
                    // 取款
                    withdraw();
                    break;
                case 4:
                    // 转账
                    transfer();
                    break;
                case 5:
                    // 修改密码
                    changePassWord();
                    return; // 跳出并结束当前方法
                case 6:
                    // 退出
                    System.out.println(loginAcc.getUserName() + "您退出系统成功！");
                    return; // 跳出并结束当前方法
                case 7:
                    // 注销当前账户
                    if (deleteAccount()) {
                        // 销户成功,回到登录界面
                        return;
                    }
                    break;
                default:
                    System.out.println("您当前选择的操作是不存在的,请确认~~");
            }
        }
    }

    /**
     * 修改密码功能
     */
    private void changePassWord() {
        System.out.println("=====账户密码修改操作=====");
        while (true) {
            // 1.提醒用户认证当前密码
            System.out.print("请您输入当前账户的密码：");
            String passWord = sc.next();

            // 2.认证当前密码是否正确啊
            if (loginAcc.getPassWord().equals(passWord)) {
                // 认证通过
                while (true) {
                    // 3.真正开始修改密码了
                    System.out.print("请您输入新密码：");
                    String newPassWord = sc.next();

                    System.out.print("请您再次输入密码：");
                    String okPassWord = sc.next();

                    // 4.判断2次 密码是否一致
                    if (okPassWord.equals(newPassWord)) {
                        // 可以真正开始修改密码了
                        loginAcc.setPassWord(okPassWord);
                        System.out.println("恭喜您,您的密码修改成功~~~");
                        return;
                    } else {
                        System.out.println("您输入的2次密码不一致~~");
                    }
                }
            } else {
                System.out.println("您当前输入的密码不正确~~");
            }
        }
    }

    /**
     * 销户功能
     *
     * @return true:销户成功 false:销户失败
     */
    private boolean deleteAccount() {
        System.out.println("=====进行销户操作=====");
        // 1.询问用户是否确定要销户
        System.out.print("请问您确认销户吗? y/n: ");
        String command = sc.next();
        switch (command) {
            case "y":
                // 确实要销户
                // 2.判断用户的账户中是否有钱：loginAcc
                if (loginAcc.getMoney() == 0) {
                    // 真的销户了
                    accounts.remove(loginAcc);
                    System.out.println("您好,您的账户已经成功销户~~");
                    return true;
                } else {
                    System.out.println("对不起,您的账户中存钱金额,不允许销户~~");
                    return false;
                }
            default:
                System.out.println("好的,您的账户保留！！");
                return false;
        }
    }

    /**
     * 转账功能
     */
    private void transfer() {
        System.out.println("=====转账功能=====");
        // 1.判断系统中是否存在其他账户
        if (accounts.size() < 2) {
            System.out.println("对不起,系统没有其他账户,无法进行转账~~");
            return;
        }

        // 2.判断自己的账户中是否有钱
        if (loginAcc.getMoney() == 0) {
            System.out.println("对不起,您的账户余额不足,无法进行转账~~");
            return;
        }

        while (true) {
            // 3.开始转账
            System.out.print("请输入您要转账的卡号：");
            String cardId = sc.next();

            // 4.判断卡号是否存在
            Account acc = getAccountById(cardId);
            if (acc == null) {
                System.out.println("对不起,您输入的卡号不存在,无法进行转账~~");
                return;
            } else {
                // 说明对方的账户存在
                String name = "*" + acc.getUserName().substring(1);
                System.out.println("请您输入【" + name + "】的姓氏：");
                String firstName = sc.next();
                // 5.判断姓氏是否正确
                if (acc.getUserName().startsWith(firstName)) {
                    while (true) {
                        // 认证通过了：真正转账了
                        System.out.println("请您输入转账给对方的金额：");
                        double money = sc.nextDouble();
                        // 6.判断转账金额是否超过了账户的限额
                        if (loginAcc.getMoney() >= money) {
                            // 开始转账
                            // 6.1 更新自己的账户余额
                            loginAcc.setMoney(loginAcc.getMoney() - money);
                            // 6.2 更新对方的账户余额
                            acc.setMoney(acc.getMoney() + money);
                            System.out.println("转账成功！");
                            return;
                        } else {
                            System.out.println("您余额不足,无法给对方转这么多钱,最多可转：" + loginAcc.getMoney());
                        }
                    }
                } else {
                    System.out.println("对不起,您输入的姓氏错误,无法进行转账~~");
                }
            }
        }
    }

    /**
     * 取款功能
     */
    private void withdraw() {
        System.out.println("=====取款功能=====");
        // 1.判断当前账户余额是否达到了100远,如果不够100元就不给用户取钱了
        if (loginAcc.getMoney() < 100) {
            System.out.println("对不起,您的账户余额不足100元,无法进行取款~~");
            return;
        }

        // 2.让用户输入取款金额
        while (true) {
            System.out.print("请输入您要取款的金额：");
            double money = sc.nextDouble();

            // 3.判断账户余额是否足够
            if (loginAcc.getMoney() >= money) {
                // 4.判断当前取款金额是否超过了账户的限额
                if (money > loginAcc.getLimit()) {
                    System.out.println("对不起,您输入的取款金额超过了账户的限额为" + loginAcc.getLimit() + "元,无法进行取款~~");
                } else {
                    // 5.更新当前登录账户的余额
                    loginAcc.setMoney(loginAcc.getMoney() - money);
                    System.out.println("恭喜您,您成功取款了" + money + "元,当前余额为：" + loginAcc.getMoney());
                    break; // 结束当前方法
                }
            } else {
                System.out.println("对不起,您的账户余额不足" + money + "元,无法进行取款~~");
            }
        }
    }

    /**
     * 存款功能
     */
    private void deposit() {
        System.out.println("=====存款功能=====");
        System.out.print("请输入您要存款的金额：");
        double money = sc.nextDouble();
        if (money > 0) {
            // 更新当前登录账户的余额
            loginAcc.setMoney(loginAcc.getMoney() + money);
            System.out.println("恭喜您,您成功存款了" + money + "元,当前余额为：" + loginAcc.getMoney());
        } else {
            System.out.println("您输入的存款金额有误,存款失败~~");
            return;
        }
    }

    /**
     * 展示当前登录的账户信息
     */
    private void showLoginAccount() {
        System.out.println("=====当前登录账户信息=====");
        System.out.println("卡号：" + loginAcc.getCardId());
        System.out.println("户主：" + loginAcc.getUserName());
        System.out.println("性别：" + loginAcc.getSex());
        System.out.println("余额：" + loginAcc.getMoney());
        System.out.println("每次取现额度：" + loginAcc.getLimit());
    }

    /**
     * 完成开户功能
     */
    private void createAccount() {
        System.out.println("=====进入开户功能=====");
        // 1.创建一个账户对象,用户封装账户的开户信息
        Account account = new Account();

        // 2.需要用户输入自己的开户信息,赋值给账户对象信息
        System.out.print("请输入您的账户名称：");
        String name = sc.next();
        account.setUserName(name);

        while (true) {
            System.out.print("请输入您的性别：");
            char sex = sc.next().charAt(0);
            if (sex == '男' || sex == '女') {
                account.setSex(sex);
                break;
            } else {
                System.out.println("性别输入错误,请重新输入");
            }
        }

        while (true) {
            System.out.print("请输入您的密码：");
            String passWord = sc.next();
            System.out.print("请输入您的确认密码：");
            String okPassWord = sc.next();
            // 判断密码是否一致
            if (passWord.equals(okPassWord)) {
                account.setPassWord(okPassWord);
                break;
            } else {
                System.out.println("您输入的2次密码不一致,请您确认~~");
            }
        }

        while (true) {
            System.out.print("请输入您的取现额度：");
            double limit = sc.nextDouble();
            if (limit > 0) {
                account.setLimit(limit);
                break;
            } else {
                // 防止用户乱输入
                System.out.println("取现额度不能小于0,请重新输入：");
            }
        }

        // 重点：我们需要为这个账户生成一个卡号（由系统自动生成,8位数字表示,不能与其他账户的卡号重复：会在下节课详细讲解）
        String newCardId = createCardId();
        account.setCardId(newCardId);

        // 3.把这个账户对象,存入到账户集合中去
        accounts.add(account);
        System.out.println("恭喜您," + account.getUserName() + "开户成功,您的卡号是：" + account.getCardId());
    }

    /**
     * 生成一个8位数字的卡号,而且这个卡号不能和其他账户的卡号重复
     *
     * @return 返回生成的卡号
     */
    private String createCardId() {
        while (true) {
            // 1.定义一个String类型的变量记住8位数字作为一个卡号
            String cardId = "";
            // 2.使用循环,循环8次,每次产生一个随机数cardId
            Random r = new Random();
            for (int i = 0; i < 8; i++) {
                int data = r.nextInt(10);
                cardId += data;
            }
            // 3.判断cartId中记住的卡号,是否和其他账户的卡号重复了,没有重复,才可以作为一个新卡号返回
            Account account = getAccountById(cardId);
            if (account == null) {
                // 如果返回的值是null,说明没有重复,该卡号可以使用
                return cardId;
            }
        }
    }

    /**
     * 根据卡号查询账户信息
     *
     * @param cardId 卡号
     * @return 如果返回null, 说明没有找到这个卡号的账户对象该卡号可以使用 如果返回Account对象,说明找到了这个卡号的账户对象,说明卡号不能使用
     */
    private Account getAccountById(String cardId) {
        // 遍历全部账户对象
        for (int i = 0; i < accounts.size(); i++) {
            Account acc = accounts.get(i);
            // 判断当前账户对象的卡号是否和输入的卡号一致
            if (acc.getCardId().equals(cardId)) {
                // 如果一致,就返回这个账户对象
                return acc;
            }
        }
        // 说明遍历了全部账户,没有找到这个卡号对应的账户对象
        return null;
    }
}
